package dm.ast;

import test.envset.GlobalState;

/**
 * Dm的表达式基础类，不包含bool表达式
 * 展开的AST可包含运算符
 */
public class DmExpression extends DmASTNode{

    String alias = null;  //别名，仅用于查询列

    public DmDataType reType = null;  //表达式的返回类型

    DmASTNode expLeft = null;   //左操作数
    DmASTNode expRight = null;   //右操作数
    DmOperator op = null;   //运算符

    public DmExpression() {
        setComplexity();
    }

    @Override
    public DmDataType getExpressionType() {
        return reType;
    }

    public DmASTNode getLeftExp() {
        return this.expLeft;
    }

    public void setLeftExp(DmASTNode expression) {
        this.expLeft = expression;
    }

    public DmASTNode getRightExp() {
        return this.expRight;
    }

    public void setRightExp(DmASTNode expression) {
        this.expRight = expression;
    }

    public DmOperator getOperator() {
        return this.op;
    }

    public void setOperator(DmOperator op) {
        this.op = op;
    }

    //交换左操作数，右操作数的顺序
    public void changeLeftRight(){
        DmASTNode tmp = expLeft;
        expLeft = expRight;
        expRight = tmp;
    }

    @Override
    public void setWidt() {
        if(expLeft == null){
            wid_t = 3;
        }else {
            expLeft.setWidt();
            wid_t = expLeft.getWidt();
            if(op != null){
                wid_t += op.getWidt();
            }
            if(expRight != null){
                expRight.setWidt();;
                wid_t += expRight.getWidt();
            }
        }
    }

    @Override
    public void setDept() {
        if(expLeft == null){
            dep_t = 1;
        }else {
            expLeft.setDept();
            dep_t = expLeft.getDept();
            if(expRight != null){
                expRight.setDept();
                if(expRight.getDept() > dep_t){
                    dep_t = expRight.getDept();
                }
            }
        }
    }

    @Override
    public String toSql(){
        StringBuilder sql = new StringBuilder();
        if(expLeft == null){
            sql.append(this.getClass().getSimpleName() + getSqlTarget());
        }else {
            if(op == null){

                //sql.append(expLeft.toSqlClose());
                sql.append(expLeft.toSql());
            }else {
                if(op.getExpNum() == 2){  //二元操作符
                    //sql.append(expLeft.toSqlClose());
                    sql.append(expLeft.toSql());
                    sql.append(op.toSql());
                    //sql.append(expRight.toSqlClose());
                    sql.append(expRight.toSql());
                }else {  //一元操作符
                    if(op.getIsPre()){
                        sql.append(op.toSql());
                        sql.append(expLeft.toSqlClose());
                    }else {
                        sql.append(expLeft.toSqlClose());
                        sql.append(op.toSql());
                    }
                }
            }
        }
        return sql.toString();
    }

    //别名需要再查询列的子句中处理
    public String toSelectElementSql(){
        String tmp = toSql();
        if(alias != null){
            return tmp + " AS " + alias;

        }else {
            return tmp;
        }
    }

    //设置查询列别名
    public void setSelEleAlias(String alias){
        this.alias = alias;
    }

    @Override
    public void fill(GlobalState globalState) {

        //需要获取当前可用的表的集合

        if(expLeft == null){
            throw new AssertionError();
        }
        expLeft.fill(globalState);
        if(expRight != null){
            expRight.fill(globalState);
        }
    }

    //处理sql错误
    //-4097|单行子查询返回多行
    public static void fixErr4097Low(DmASTNode exp){
        if(exp == null){
            return;
        }
        if(exp instanceof DmSubSelect){
            ((DmSubSelect) exp).fixErr4097();

        }else if(exp instanceof DmExpression){
            ((DmExpression) exp).fixErr4097();
        }
    }

    //处理sql错误
    //-4097|单行子查询返回多行
    public void fixErr4097(){
        fixErr4097Low(expLeft);
        fixErr4097Low(expRight);
    }


}
